package edu.toronto.whimper;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;

public class NoiseLevel extends Activity {

    // ******************************************************************** //
    // Private Data.
    // ******************************************************************** //

    

    private static TextView textViewCurrentNoiseLevel, textViewAverageNoiseLevel, textViewSmoothedNoiseLevel;
    private static TextView textViewLongitudeValue, textViewLatitudeValue, textViewAltitudeValue;
    
    
    ///////////////////////////////////////////////////////
    
    //private NoiseMeter localNoiseMeter = null;

    private int refreshDelay = 100;
    
    ThreadTicker localThreadTicker = null;
    
    Handler mainThreadHandler;

	static private final int PREFERENCES_CALL_CODE = 100;

    // ******************************************************************** //
    // Activity Lifecycle.
    // ******************************************************************** //

    /**
     * Called when the activity is starting.  This is where most
     * initialisation should go: calling setContentView(int) to inflate
     * the activity's UI, etc.
     * 
     * You can call finish() from within this function, in which case
     * onDestroy() will be immediately called without any of the rest of
     * the activity lifecycle executing.
     * 
     * Derived classes must call through to the super class's implementation
     * of this method.  If they do not, an exception will be thrown.
     * 
     * @param   icicle          If the activity is being re-initialised
     *                          after previously being shut down then this
     *                          Bundle contains the data it most recently
     *                          supplied in onSaveInstanceState(Bundle).
     *                          Note: Otherwise it is null.
     */
    @Override
    public void onCreate(Bundle icicle) {
    	
        super.onCreate(icicle);
        
        // We want the audio controls to control our sound volume.
        //this.setVolumeControlStream(AudioManager.STREAM_MUSIC);

        // Create the application GUI.

        setContentView(R.layout.noiselevel);
        textViewCurrentNoiseLevel = (TextView) findViewById(R.id.textViewCurrentNoiseValue);
        textViewAverageNoiseLevel = (TextView) findViewById(R.id.textViewAverageNoiseValue);
        textViewSmoothedNoiseLevel = (TextView) findViewById(R.id.textViewSmoothedNoiseValue);
        
        textViewLongitudeValue = (TextView) findViewById(R.id.textViewLongitudeValue);
        textViewLatitudeValue = (TextView) findViewById(R.id.textViewLatitudeValue);
        textViewAltitudeValue = (TextView) findViewById(R.id.textViewAltitudeValue);
        
        // Restore our preferences.
        
    	if (icicle == null){
    		localInit();
    	}
        
        
    }
    

    /**
     * Called after {@link #onCreate} or {@link #onStop} when the current
     * activity is now being displayed to the user.  It will
     * be followed by {@link #onRestart}.
     */
    @Override
    protected void onStart() {
        super.onStart();
    }


    /**
     * Called after onRestoreInstanceState(Bundle), onRestart(), or onPause(),
     * for your activity to start interacting with the user.  This is a good
     * place to begin animations, open exclusive-access devices (such as the
     * camera), etc.
     * 
     * Derived classes must call through to the super class's implementation
     * of this method.  If they do not, an exception will be thrown.
     */
    @Override
    protected void onResume() {
        super.onResume();
    }


    /**
     * Called to retrieve per-instance state from an activity before being
     * killed so that the state can be restored in onCreate(Bundle) or
     * onRestoreInstanceState(Bundle) (the Bundle populated by this method
     * will be passed to both).
     * 
     * @param   outState        A Bundle in which to place any state
     *                          information you wish to save.
     */
    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
    }

    
    /**
     * Called as part of the activity lifecycle when an activity is going
     * into the background, but has not (yet) been killed.  The counterpart
     * to onResume(). 
     */
    @Override
    protected void onPause() {
        super.onPause();
        
    }


    /**
     * Called when you are no longer visible to the user.  You will next
     * receive either {@link #onStart}, {@link #onDestroy}, or nothing,
     * depending on later user activity.
     */
    @Override
    protected void onStop() {
        super.onStop();

    }
    
    @Override
    protected void onDestroy() {
    	super.onDestroy();
    	localThreadTicker.kill();
    }

    public void noiselevelButtonClickHandler(View clickedButton){
    	switch(clickedButton.getId()){
    	case R.id.buttonNoiseLevelPlay:
    		Main.mainNoiseMeter.measureStart();
    		Main.mainGPSReader.StartRecieving();
    		break;
    	case R.id.buttonNoiseLevelStop:
    		Main.mainNoiseMeter.measureStop();
    		Main.mainGPSReader.StopRecieving();
    		break;
    	}
    }
 

    public void mainThreadMessageHandler(Message msg){
    	updateCurrentPower();
    }

    private void localInit(){
    	//localNoiseMeter = new NoiseMeter();
    	
    	mainThreadHandler = new Handler(){
        	public void handleMessage(Message msg){
        		mainThreadMessageHandler(msg);
        	}
        };
    	
    	localThreadTicker = new ThreadTicker();

    }
    
    private void updateCurrentPower(){
    	float currentNoise, averageNoise, smoothedNoise;
    	
    	currentNoise  = Main.mainNoiseMeter.GetCurrentNoise();
    	averageNoise  = Main.mainNoiseMeter.GetAverageNoise();
    	smoothedNoise = Main.mainNoiseMeter.GetSmoothedNoise();
    	
    	currentNoise = (float)( (int) (10*currentNoise)) /10;
    	averageNoise = (float)( (int) (10*averageNoise)) /10;
    	smoothedNoise = (float)( (int) (10*smoothedNoise)) /10;

    	textViewCurrentNoiseLevel.setText(currentNoise+" db");
    	textViewAverageNoiseLevel.setText(averageNoise+" db");
    	textViewSmoothedNoiseLevel.setText(smoothedNoise+" db");
    	
    	double longitude, latitude, altitude;
    	
    	longitude = Main.mainGPSReader.GetCurrentLocationLongitude();
    	latitude = Main.mainGPSReader.GetCurrentLocationLatitude();
    	altitude = Main.mainGPSReader.GetCurrentLocationAltitude();
    	
    	textViewLongitudeValue.setText(longitude+"");
    	textViewLatitudeValue.setText(latitude+"");
    	textViewAltitudeValue.setText(altitude+"");
    }
    
    private void tick(){
    	mainThreadHandler.sendMessage(mainThreadHandler.obtainMessage());
    }
    
	/**
	 * Thread-based ticker class.  This may be faster than LoopTicker.
	 */
	private class ThreadTicker
	    extends Thread
	{

	    // Constructor -- start at once.
	    private ThreadTicker() {
	        super("Surface Runner");
	        enable = true;
	        start();
	    }

	    // Stop this thread.  There will be no new calls to tick() after this.
	    public void kill() {
	        enable = false;
	    }

	    // Stop this thread and wait for it to die.  When we return, it is
	    // guaranteed that tick() will never be called again.
	    // 
	    // Caution: if this is called from within tick(), deadlock is
	    // guaranteed.
	    public void killAndWait() {
	        if (Thread.currentThread() == this)
	        	throw new IllegalStateException("ThreadTicker.killAndWait()" +
	        								    " called from ticker thread");

	        enable = false;

	        // Wait for the thread to finish.  Ignore interrupts.
	        if (isAlive()) {
	            boolean retry = true;
	            while (retry) {
	                try {
	                    join();
	                    retry = false;
	                } catch (InterruptedException e) { }
	            }
	        } else {
	        }
	    }

	    // Run method for this thread -- simply call tick() a lot until
	    // enable is false.
	    @Override
	    public void run() {
	        while (enable) {
	            tick();
	            
                if (refreshDelay > 0) try {
                    sleep(refreshDelay);
                } catch (InterruptedException e) { }
	        }
	    }
	    
	    // Flag used to terminate this thread -- when false, we die.
	    private boolean enable = false;
	}
	

}
